// Binary server is an example server.
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"gin-gateway/core/init"
	pb "gin-gateway/example/grpc_gateway/proto"
	"google.golang.org/grpc"
)

// var port = flag.Int("port", 50055, "the port to serve on")

var serviceName = "test_grpc_service"

const (
	streamingCount = 10
)

type server struct {
	pb.UnimplementedEchoServer
}

func (s *server) ServerStreamingEcho(in *pb.EchoRequest, stream pb.Echo_ServerStreamingEchoServer) error {
	fmt.Printf("--- ServerStreamingEcho ---\n")
	fmt.Printf("request received: %v\n", in)
	// Read requests and send responses.
	for i := 0; i < streamingCount; i++ {
		fmt.Printf("echo message %v\n", in.Message)
		err := stream.Send(&pb.EchoResponse{Message: in.Message})
		if err != nil {
			return err
		}
	}
	return nil
}

func (s *server) ClientStreamingEcho(stream pb.Echo_ClientStreamingEchoServer) error {
	fmt.Printf("--- ClientStreamingEcho ---\n")
	// Read requests and send responses.
	var message string
	for {
		in, err := stream.Recv()
		if err == io.EOF {
			fmt.Printf("echo last received message\n")
			return stream.SendAndClose(&pb.EchoResponse{Message: message})
		}
		message = in.Message
		fmt.Printf("request received: %v, building echo\n", in)
		if err != nil {
			return err
		}
	}
}

func (s *server) BidirectionalStreamingEcho(stream pb.Echo_BidirectionalStreamingEchoServer) error {
	fmt.Printf("--- BidirectionalStreamingEcho ---\n")
	// Read requests and send responses.
	for {
		in, err := stream.Recv()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		fmt.Printf("request received %v, sending echo\n", in)
		if err := stream.Send(&pb.EchoResponse{Message: in.Message}); err != nil {
			return err
		}
	}
}

func (s *server) UnaryEcho(ctx context.Context, in *pb.EchoRequest) (*pb.EchoResponse, error) {
	fmt.Printf("--- UnaryEcho ---\n")
	// md, ok := metadata.FromIncomingContext(ctx)
	// if !ok {
	// 	log.Println("miss metadata from context")
	// }
	// fmt.Println("md", md)
	fmt.Printf("request received: %v, sending echo\n", in)
	return &pb.EchoResponse{Message: in.Message}, nil
}

func main() {
	// flag.Parse()

	// BACKEND_SCHEME 格式： "grpcbackend,50055,50"
	sc := strings.Split(os.Getenv("BACKEND_SCHEME"), ",")
	if len(sc) != 3 {
		log.Fatal("BACKEND_SCHEME should be set")
	}

	addr := fmt.Sprintf("0.0.0.0:%s", sc[1])
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	log.Printf("starting grpcserver at %v\n", addr)
	s := grpc.NewServer()
	pb.RegisterEchoServer(s, &server{})

	etcdServer := os.Getenv("ETCD_SERVER")
	if len(etcdServer) == 0 {
		log.Fatal("ETCD_SERVER should be set")
	}
	registry, err := Init.NewEtcdRegistry([]string{etcdServer}, time.Duration(5))
	if err != nil {
		panic(err)
	}

	endpoint := fmt.Sprintf("%s/%s", serviceName, sc[1])
	// 注册格式： "grpcbackend:50055,50"
	err = registry.Register(endpoint, fmt.Sprintf("%s:%s,%s", sc[0], sc[1], sc[2]))
	if err != nil {
		panic(err)
	}

	go func() {
		s.Serve(lis)
	}()

	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	err = registry.Unregister(context.Background(), endpoint)
	if err != nil {
		fmt.Println("unregister")
		panic(err)
	}
	err = registry.Close()
	if err != nil {
		panic(err)
	}
}
